#pragma once
#include <deque>
#include <map>
#include <mutex>
#include <thread>
#include <vector>
#include <conio.h>
#include "Player.h"
#include "Console.h"

using namespace std;
using namespace Course;

class Game
{
private:
	vector<vector<char>> map;
	int map_size;
	deque<char> *player_queue1;
	deque<char> *player_queue2;
	deque<Pos> *game_queue;
	char *c;

public:
	Game(void)
	{
	}

	Game(int size, deque<char> &player_queue1, deque<char> &player_queue2, deque<Pos> &game_queue)
	{
		this->map_size = size;
		this->map = vector<vector<char>>(size);
		for(int i = 0; i < size; i++)
		{
			map[i] = vector<char>(size);
		}
		for(int row = 0; row < map_size; row++)
		{
			for(int column = 0; column < map_size; column++)
				map[row][column] = '.';
		}
		this->player_queue1 = &player_queue1;
		this->player_queue2 = &player_queue2;
		this->game_queue = &game_queue;
	}

	void update()
	{
		Pos pos;

		mtx_game_queue.lock();
		if(!game_queue->empty())
		{
			pos = game_queue->front();
			game_queue->pop_front();

			for(int row = 0; row < map_size; row++)
			{
				for(int column = 0; column < map_size; column++)
				{
					if(map[row][column] == pos.id)
					{
						map[row][column] = '.';
					}
				}
			}
			int x = pos.x_pos;
			int y = pos.y_pos;
			map[y][x] = pos.id;
		}
		mtx_game_queue.unlock();
	}

	void push_queue(char c)
	{
		//char c = _getch();
		mtx_player_queue.lock();
		if(c == 'w' || c == 'a' || c == 's' || c == 'd')
			player_queue1->push_back(c);
		if(c == 'i' || c == 'j' || c == 'k' || c == 'l')
			player_queue2->push_back(c);
		mtx_player_queue.unlock();
	}

	void draw()
	{
		Console::clrscr();
		for(int row = 0; row < map_size; row++)
		{
			for(int column = 0; column < map_size; column++)
			{
				cout << (char)map[row][column] << " ";
			}
			cout << endl;
		}
	}

	void operator()()
	{
		char c = ' ';
		if(_kbhit() != 0)
		{
			c = _getch();
		}

		while(c != 'e') //e = exit
		{
			draw();
			push_queue(c);
			c = ' ';
			update();
			this_thread::sleep_for(chrono::milliseconds(100)); //(chrono::microseconds(100));
			if(_kbhit() != 0)
			{
				c = _getch();
			}
		}
	}

	~Game(void)
	{
	}
};

